package org.lgiavedoni.android.franq.util.date;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {

	public static final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
	public static final long MILLISECONDS_PER_YEAR = MILLISECONDS_PER_DAY * 365;
	public static final String DATE_FORMAT_YYYYMMDD_KEY = "yyyyMMdd";
	public static final String DATE_FORMAT_YYYYMMDD_HHMMSS_KEY = "yyyy/MM/dd HH:mm:ss";
	public static final String DATE_FORMAT_HHMM_KEY = "HH:mm";

	public static String getDateYYYYMMDD() {
		return new SimpleDateFormat(DATE_FORMAT_YYYYMMDD_KEY).format(new Date());
	}

	public static String getDateHHmm(Date date) {
		return new SimpleDateFormat(DATE_FORMAT_HHMM_KEY).format(date);
	}

	public static int getDayOfWeek(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_WEEK);
	}

	public static int getDayOfYear(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_YEAR);
	}

	public static String getDayOfWeekAsString(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return parseDayOfWeekToString(calendar.get(Calendar.DAY_OF_WEEK));
	}

	public static int getHourOfDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.HOUR_OF_DAY);
	}

	public static String getTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE);
	}

	public static int getHour(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.HOUR_OF_DAY);
	}

	public static long getMillisecondsOfMins(int mins) {
		return Long.valueOf(mins * 1000 * 60);
	}

	public static long getMillisecondsOfHours(int hours) {
		return Long.valueOf(hours * 60 * 60 * 1000);
	}

	public static long getTimeInMillis() {
		return Calendar.getInstance().getTimeInMillis();
	}

	public static String parseDateTime(long time) {
		return parseDateTime(new Date(time));
	}

	public static String parseDateTime(Date date) {
		return new SimpleDateFormat(DATE_FORMAT_YYYYMMDD_HHMMSS_KEY).format(date);
	}

	public static Date addDays(Date initDate, int numOfDaysToAdd) {
		Calendar c = Calendar.getInstance();
		c.setTime(initDate);
		c.add(Calendar.DAY_OF_YEAR, numOfDaysToAdd);
		return c.getTime();

	}

	public static int getField(Date d, int field) {
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		return c.get(field);
	}

	/*
	 * public static boolean isSameDay(Date a, Date b) { if (a == null || b ==
	 * null) return false; return getDayOfYear(a) == getDayOfYear(b); }
	 */

	public static String parseDayOfWeekToString(int day) {
		String[] strDays = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thusday", "Friday", "Saturday" };
		return strDays[day - 1];
	}

	public static String getDateFileNameFormat() {
		return String.valueOf(getTimeInMillis());
	}

	public static int getNextDayOfTheYear(Date date, int dayOfTheWeek) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		if (calendar.get(Calendar.DAY_OF_WEEK) > dayOfTheWeek) {
			calendar.set(Calendar.DAY_OF_WEEK, dayOfTheWeek);
			return calendar.get(Calendar.DAY_OF_YEAR) + 7;
		}
		calendar.set(Calendar.DAY_OF_WEEK, dayOfTheWeek);
		return calendar.get(Calendar.DAY_OF_YEAR);
	}

	public static int getNextDayOfTheYear(int dayOfTheWeek) {
		return getNextDayOfTheYear(new Date(), dayOfTheWeek);

	}

	public static int countDaysOfTheWeek(Date since, int dayOfTheWeek) {
		Calendar now = Calendar.getInstance();
		Calendar sinceC = Calendar.getInstance();
		sinceC.setTime(since);

		long dayDiff = (now.getTime().getTime() - since.getTime()) / MILLISECONDS_PER_DAY / 7;
		long resto = (now.getTime().getTime() - since.getTime()) / MILLISECONDS_PER_DAY % 7;
		if (resto >= (getNextDayOfTheYear(since, dayOfTheWeek) - sinceC.get(Calendar.DAY_OF_YEAR)))
			dayDiff++;

		return (int) dayDiff;
	}

	/**
	 * <p>
	 * Checks if two dates are on the same day ignoring time.
	 * </p>
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException
	 *             if either date is <code>null</code>
	 */
	public static boolean isSameDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isSameDay(cal1, cal2);
	}

	/**
	 * <p>
	 * Checks if two calendars represent the same day ignoring time.
	 * </p>
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null
	 * @param cal2
	 *            the second calendar, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException
	 *             if either calendar is <code>null</code>
	 */
	public static boolean isSameDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.DAY_OF_YEAR) == cal2
				.get(Calendar.DAY_OF_YEAR));
	}

	/**
	 * <p>
	 * Checks if a date is today.
	 * </p>
	 * 
	 * @param date
	 *            the date, not altered, not null.
	 * @return true if the date is today.
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isToday(Date date) {
		return isSameDay(date, Calendar.getInstance().getTime());
	}

	/**
	 * <p>
	 * Checks if a calendar date is today.
	 * </p>
	 * 
	 * @param cal
	 *            the calendar, not altered, not null
	 * @return true if cal date is today
	 * @throws IllegalArgumentException
	 *             if the calendar is <code>null</code>
	 */
	public static boolean isToday(Calendar cal) {
		return isSameDay(cal, Calendar.getInstance());
	}

	/**
	 * <p>
	 * Checks if the first date is before the second date ignoring time.
	 * </p>
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if the first date day is before the second date day.
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isBeforeDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isBeforeDay(cal1, cal2);
	}

	public static boolean isBeforeDay(Date date1) {
		return isBeforeDay(date1, new Date());
	}

	/**
	 * <p>
	 * Checks if the first calendar date is before the second calendar date
	 * ignoring time.
	 * </p>
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null.
	 * @param cal2
	 *            the second calendar, not altered, not null.
	 * @return true if cal1 date is before cal2 date ignoring time.
	 * @throws IllegalArgumentException
	 *             if either of the calendars are <code>null</code>
	 */
	public static boolean isBeforeDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		if (cal1.get(Calendar.ERA) < cal2.get(Calendar.ERA))
			return true;
		if (cal1.get(Calendar.ERA) > cal2.get(Calendar.ERA))
			return false;
		if (cal1.get(Calendar.YEAR) < cal2.get(Calendar.YEAR))
			return true;
		if (cal1.get(Calendar.YEAR) > cal2.get(Calendar.YEAR))
			return false;
		return cal1.get(Calendar.DAY_OF_YEAR) < cal2.get(Calendar.DAY_OF_YEAR);
	}

	public static boolean isHourBetween(int hourIni, int hourEnd) {
		Calendar cal1 = Calendar.getInstance();
		int hour = cal1.get(Calendar.HOUR_OF_DAY);
		return hour >= hourIni && hour <= hourEnd;
	}

	/**
	 * <p>
	 * Checks if the first date is after the second date ignoring time.
	 * </p>
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if the first date day is after the second date day.
	 * @throws IllegalArgumentException
	 *             if the date is <code>null</code>
	 */
	public static boolean isAfterDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isAfterDay(cal1, cal2);
	}

	/**
	 * <p>
	 * Checks if the first calendar date is after the second calendar date
	 * ignoring time.
	 * </p>
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null.
	 * @param cal2
	 *            the second calendar, not altered, not null.
	 * @return true if cal1 date is after cal2 date ignoring time.
	 * @throws IllegalArgumentException
	 *             if either of the calendars are <code>null</code>
	 */
	public static boolean isAfterDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The dates must not be null");
		}
		if (cal1.get(Calendar.ERA) < cal2.get(Calendar.ERA))
			return false;
		if (cal1.get(Calendar.ERA) > cal2.get(Calendar.ERA))
			return true;
		if (cal1.get(Calendar.YEAR) < cal2.get(Calendar.YEAR))
			return false;
		if (cal1.get(Calendar.YEAR) > cal2.get(Calendar.YEAR))
			return true;
		return cal1.get(Calendar.DAY_OF_YEAR) > cal2.get(Calendar.DAY_OF_YEAR);
	}

	public static void main(String a[]) {
		System.out.println(countDaysOfTheWeek(new Date("11/07/2010"), Calendar.MONDAY));
		System.out.println(countDaysOfTheWeek(new Date("11/07/2010"), Calendar.FRIDAY));
		System.out.println(countDaysOfTheWeek(new Date("10/28/2010"), Calendar.FRIDAY));
	}

}
